#include "virtual_gpio.h"

static uint32_t direction = 0;
static uint32_t output = 0;

//获取 IO 方向，0输出，1输入
static int virtual_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
	printk("get pin direction %d, it's direction = %s\n", offset, (direction & (0x01 << offset)) ? "output" : "input");
	return (direction & (0x01 << offset)) ? 0 : 1;
}

//设置为输入
static int virtual_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
	printk("set pin %d as input\n", offset);
	direction &= ~(0x01 << offset);
	return 0;
}

//设置为输出
static int virtual_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
{
	printk("set pin %d as output %s\n", offset, value ? "high" : "low");
	direction |= 0x01 << offset;
	if(value)
		output |= 0x01 << offset;
	else
		output &= ~(0x01 << offset);
	return 0;
}

//获取 IO 状态
static int virtual_gpio_get(struct gpio_chip *chip, unsigned offset)
{
	printk("get pin value %d, it's value = %s\n", offset, (output & (0x01 << offset)) ? "high" : "low");
	return (output & (0x01 << offset)) ? 1 : 0;
}

//设置 IO 状态
static void virtual_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
	printk("set pin value %d as %s\n", offset, value ? "high" : "low");
	if(value)
		output |= 0x01 << offset;
	else
		output &= ~(0x01 << offset);
}

//配置 GPIO
static int virtual_gpio_set_config(struct gpio_chip *chip, unsigned offset, unsigned long config)
{
	printk("set pin %d config %ld\n", offset, config);
	return 0;
}

//设备和驱动匹配成功执行
static int virtual_probe(struct platform_device *pdev)
{
	int result;
	uint32_t value;
	struct gpio_chip *gpio_chip;

	printk("%s\n", __FUNCTION__);

	/* 1. 分配gpio_chip */
	gpio_chip = devm_kzalloc(&pdev->dev, sizeof(struct gpio_chip), GFP_KERNEL);
	if(!gpio_chip) {
		printk("alloc gpio_chip failed\r\n");
		return -ENOMEM;
	}

	/* 2. 设置gpio_chip */
	gpio_chip->parent = &pdev->dev;
	gpio_chip->owner = THIS_MODULE;
	gpio_chip->label = pdev->name;
	/* 2.1 设置函数 */
	gpio_chip->request = gpiochip_generic_request;
	gpio_chip->free = gpiochip_generic_free;
	gpio_chip->get_direction = virtual_gpio_get_direction;
	gpio_chip->direction_input  = virtual_gpio_direction_input;
	gpio_chip->direction_output = virtual_gpio_direction_output;
	gpio_chip->get = virtual_gpio_get;
	gpio_chip->set = virtual_gpio_set;
	gpio_chip->set_config = virtual_gpio_set_config,
	
	/* 2.2 设置base、ngpio值，base==-1表示自动分配 */
	gpio_chip->base = -1;
	result = of_property_read_u32(pdev->dev.of_node, "ngpios", &value);
	if(result < 0) 
	{
		printk("get ngpios failed\r\n");
		return result;
	}
	gpio_chip->ngpio = value;

	/* 3. 注册gpio_chip */
	return devm_gpiochip_add_data(&pdev->dev, gpio_chip, NULL);;
}

//设备或驱动卸载时执行
static int virtual_remove(struct platform_device *pdev)
{
	printk("%s\n", __FUNCTION__);
	return 0;
}

/* 匹配列表，用于设备树和平台驱动匹配 */
static const struct of_device_id virtual_of_match[] = {
	{.compatible = "atk,virtual_gpio"},
	{ /* Sentinel */ }
};
/* 平台驱动 */
static struct platform_driver virtual_drv = {
	.driver = {
		.name = "virtual_gpio",
		.owner = THIS_MODULE,
		.pm = NULL,
		.of_match_table = virtual_of_match,
	},
	.probe = virtual_probe,
	.remove = virtual_remove,
};
static int __init virtual_drv_init(void)
{
	int result;

	printk("%s\r\n", __FUNCTION__);

	//注册平台驱动
	result = platform_driver_register(&virtual_drv);
	if(result != 0)
		printk("add virtual driver failed\r\n");
	return result;
}

static void __exit virtual_drv_exit(void)
{
	printk("%s\r\n", __FUNCTION__);

	//注销平台驱动
	platform_driver_unregister(&virtual_drv);
}

module_init(virtual_drv_init);
module_exit(virtual_drv_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("LF");
MODULE_DESCRIPTION("virtual_drv");
